home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 001-025 / disk_008 / src / hack.end.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  14KB  |  550 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  2. /* hack.end.c version 1.0.1 - added "escaped with amulet" */
  3.  
  4. #include "hack.h"
  5. #include <stdio.h>
  6. #include <fcntl.h>
  7.  
  8. #ifndef AMIGA
  9. #include <signal.h>
  10. #endif
  11.  
  12. #define   Sprintf   (void) sprintf
  13. extern char plname[], pl_character[];
  14. extern char *itoa(), *ordin(), *eos(), *getlogin();
  15.  
  16. extern char *index(); /* M.E.T. 11/20/85 */
  17.  
  18. xchar maxdlevel = 1;
  19.  
  20. done1()
  21. {
  22. #ifndef AMIGA
  23.    (void) signal(SIGINT,SIG_IGN);
  24. #endif
  25.    pline("Really quit?");
  26.    if(readchar() != 'y')
  27.       {
  28. #ifndef AMIGA
  29.       (void) signal(SIGINT,done1);
  30. #endif
  31.       clrlin();
  32.       (void) myfflush(stdout);
  33.       if(multi > 0) nomul(0);
  34.       return(0);
  35.       }
  36.    done("quit");
  37.    /* NOTREACHED */
  38. }
  39.  
  40. int done_stopprint;
  41.  
  42. done_intr(){
  43.    done_stopprint++;
  44. #ifndef AMIGA
  45.    (void) signal(SIGINT,SIG_IGN);
  46. #endif
  47. }
  48.  
  49. done_in_by(mtmp) register struct monst *mtmp; {
  50. static char buf[BUFSZ];
  51.    pline("You die ...");
  52.    if(mtmp->data->mlet == ' ')
  53.       {
  54.       Sprintf(buf, "the ghost of %s", (char *) mtmp->mextra);
  55.       killer = buf;
  56.       }
  57.    else if(mtmp->mnamelth)
  58.       {
  59.       Sprintf(buf, "%s called %s", mtmp->data->mname, NAME(mtmp));
  60.       killer = buf;
  61.       }
  62.    else if(mtmp->minvis)
  63.       {
  64.       Sprintf(buf, "invisible %s", mtmp->data->mname);
  65.       killer = buf;
  66.       }
  67.    else
  68.       killer = mtmp->data->mname;
  69.    done("died");
  70. }
  71.  
  72. /* called with arg "died", "escaped", "quit", "choked", "panic"
  73.    or "starved" */
  74. /* Be careful not to call panic from here! */
  75. done(st1)
  76. register char *st1;
  77. {
  78.  
  79. #ifdef WIZARD
  80.    if(wizard && *st1 == 'd'){
  81.       u.ustr = u.ustrmax += 2;
  82.       u.uhp = u.uhpmax += 10;
  83.       if(uarm) uarm->spe++;
  84.       if(uwep) uwep->spe++; /* NB: uwep need not be a weapon! */
  85.       u.uswldtim = 0;
  86.       pline("For some reason you are still alive.");
  87.       flags.move = 0;
  88.       if(multi > 0) multi = 0; else multi = -1;
  89.       flags.botl = 1;
  90.       return;
  91.    }
  92. #endif WIZARD
  93. #ifndef AMIGA
  94.    (void) signal(SIGINT, done_intr);
  95. #endif
  96.    if(*st1 == 'q' && u.uhp < 1)
  97.       {
  98.       st1 = "died";
  99.       killer = "quit while already on Charon's boat";
  100.       }
  101.    if(*st1 == 's')
  102.       killer = "starvation";
  103.    paybill();
  104.    clearlocks();
  105.    if(index("cds", *st1))
  106.         {
  107.         savebones();
  108.         if(!flags.notombstone)
  109.             outrip();
  110.         else
  111.             more();
  112.         }
  113.    myprintf("Contents of your pack when you died:\n");
  114.    myddoinv();
  115.    settty((char *) 0);   /* does a cls() */
  116.    if(!done_stopprint)
  117.       myprintf("Goodbye %s %s...\n\n", pl_character, plname);
  118.    {
  119.       long int tmp;
  120.       tmp = u.ugold - u.ugold0;
  121.       if(tmp < 0) tmp = 0;
  122.       if(*st1 == 'd')
  123.          tmp -= tmp/10;
  124.       else
  125.          killer = st1;
  126.       u.urexp += tmp;
  127.    }
  128.    if(*st1 == 'e')
  129.       {
  130.       extern struct monst *mydogs;
  131.       register struct monst *mtmp = mydogs;
  132.       register struct obj *otmp;
  133.       register int i;
  134.       register unsigned worthlessct = 0;
  135.  
  136.         killer = st1;
  137.     u.urexp += 50 * maxdlevel;
  138.       if(mtmp)
  139.          {
  140.          if(!done_stopprint) myprintf("You");
  141.          while(mtmp)
  142.             {
  143.             if(!done_stopprint)
  144.                myprintf(" and %s", monnam(mtmp));
  145.             u.urexp += mtmp->mhp;
  146.             mtmp = mtmp->nmon;
  147.             }
  148.          if(!done_stopprint)
  149.           myprintf("\nescaped from the dungeon with %lu points,\n",
  150.          u.urexp);
  151.          }
  152.       else if(!done_stopprint)
  153.         myprintf("You escaped from the dungeon with %lu points,\n",
  154.           u.urexp);
  155.       for(otmp = invent; otmp; otmp = otmp->nobj) {
  156.          if(otmp->olet == GEM_SYM){
  157.             objects[otmp->otyp].oc_name_known = 1;
  158.             i = otmp->quan*objects[otmp->otyp].g_val;
  159.             if(i == 0) {
  160.                worthlessct += otmp->quan;
  161.                continue;
  162.             }
  163.             u.urexp += i;
  164.             if(!done_stopprint)
  165.               myprintf("\t%s (worth %d Zorkmids),\n",
  166.                 doname(otmp), i);
  167.          } else if(otmp->olet == AMULET_SYM) {
  168.             otmp->known = 1;
  169.             i = (otmp->spe < 0) ? 2 : 5000;
  170.             u.urexp += i;
  171.             if(!done_stopprint)
  172.               myprintf("\t%s (worth %d Zorkmids),\n",
  173.                 doname(otmp), i);
  174.                 if(otmp->spe >= 0) {
  175.                     u.urexp *= 2;
  176.                     killer = "escaped (with amulet)";
  177.                 }
  178.          }
  179.       }
  180.       if(worthlessct) if(!done_stopprint)
  181.         myprintf("\t%d worthless piece%s of coloured glass,\n",
  182.         worthlessct, plur(worthlessct));
  183.    } else
  184.       if(!done_stopprint)
  185.         myprintf("You %s on dungeon level %d with %lu points,\n",
  186.           st1,dlevel,u.urexp);
  187.    if(!done_stopprint)
  188.      myprintf("and %lu piece%s of gold, after %lu move%s.\n",
  189.        u.ugold, (u.ugold == 1) ? "" : "s",
  190.        moves, (moves == 1) ? "" : "s");
  191.    if(!done_stopprint)
  192.   myprintf("You were level %d with a maximum of %d hit points when you %s.\n",
  193.        u.ulevel, u.uhpmax, st1);
  194.    if(*st1 == 'e'){
  195.       getret();   /* all those pieces of coloured glass ... */
  196.       cls();
  197.    }
  198. #ifdef WIZARD
  199.    if(!wizard)
  200. #endif WIZARD
  201.       topten();
  202.    if(done_stopprint) myprintf("\n\n");
  203.    hackexit(0);
  204. }
  205.  
  206. #define newttentry() (struct toptenentry *) alloc(sizeof(struct toptenentry))
  207. #define   NAMSZ   8
  208. #define   DTHSZ   40
  209. #define   PERSMAX   1
  210. #define   POINTSMIN   1   /* must be > 0 */
  211. #define   ENTRYMAX   100   /* must be >= 10 */
  212. struct toptenentry {
  213.    struct toptenentry *tt_next;
  214.    long int points;
  215.    int level,maxlvl,hp,maxhp;
  216.    char plchar;
  217.    char str[NAMSZ+1];
  218.    char death[DTHSZ+1];
  219. } *tt_head;
  220.  
  221. topten(){
  222.    int rank, rank0 = -1, rank1 = 0;
  223.    int occ_cnt = PERSMAX;
  224.    register struct toptenentry *t0, *t1, *tprev;
  225.    char *recfile = "record";
  226.    int  rfile;
  227.    register int flg = 0;
  228.  
  229.    if((rfile = open(recfile,O_RDONLY)) < 0)
  230.       {
  231.       myputs("Cannot open record file!");
  232.       return;
  233.       }
  234.    (void) myputchar('\n');
  235.  
  236.    /* create a new 'topten' entry */
  237.    t0 = newttentry();
  238.    t0->level = dlevel;
  239.    t0->maxlvl = maxdlevel;
  240.    t0->hp = u.uhp;
  241.    t0->maxhp = u.uhpmax;
  242.    t0->points = u.urexp;
  243.    t0->plchar = pl_character[0];
  244.    (void) strncpy(t0->str, plname, NAMSZ);
  245.    (t0->str)[NAMSZ] = 0;
  246.    (void) strncpy(t0->death, killer, DTHSZ);
  247.    (t0->death)[DTHSZ] = 0;
  248.  
  249.    /* assure minimum number of points */
  250.    if(t0->points < POINTSMIN)
  251.       t0->points = 0;
  252.  
  253.    t1 = tt_head = newttentry();
  254.    tprev = 0;
  255.    /* rank0: -1 undefined, 0 not_on_list, n n_th on list */
  256.    for(rank = 1; ; ) {
  257.      if (read(rfile, t1, sizeof(struct toptenentry)) !=
  258.            sizeof(struct toptenentry) || (t1->points < POINTSMIN))
  259.         t1->points = 0;
  260.  
  261.      if(rank0 < 0 && t1->points < t0->points) {
  262.       rank0 = rank++;
  263.       if(tprev == 0)
  264.          tt_head = t0;
  265.       else
  266.          tprev->tt_next = t0;
  267.       t0->tt_next = t1;
  268.       occ_cnt--;
  269.       flg++;      /* ask for a rewrite */
  270.      } else
  271.       tprev = t1;
  272.      if(t1->points == 0) break;
  273.      if(strncmp(t1->str, t0->str, NAMSZ) == 0 &&
  274.         t1->plchar == t0->plchar && --occ_cnt <= 0){
  275.       if(rank0 < 0){
  276.          rank0 = 0;
  277.          rank1 = rank;
  278.    myprintf("You didn't beat your previous score of %ld points.\n\n",
  279.             t1->points);
  280.       }
  281.       if(occ_cnt < 0){
  282.          flg++;
  283.          continue;
  284.       }
  285.      }
  286.      if(rank <= ENTRYMAX){
  287.         t1 = t1->tt_next = newttentry();
  288.         rank++;
  289.      }
  290.      if(rank > ENTRYMAX){
  291.       t1->points = 0;
  292.       break;
  293.      }
  294.    }
  295.    if(flg) {   /* rewrite record file */
  296.       (void) close(rfile);
  297.       if((rfile=open(recfile,O_WRONLY)) < 0)
  298.          {
  299.          myputs("Cannot write record file\n");
  300.          return;
  301.          }
  302.  
  303.       if(!done_stopprint) if(rank0 > 0){
  304.           if(rank0 <= 10)
  305.          myputs("You made the top ten list!\n");
  306.           else
  307.       myprintf("You reached the %d%s place on the top %d list.\n\n",
  308.          rank0, ordin(rank0), ENTRYMAX);
  309.       }
  310.    }
  311.    if(rank0 == 0) rank0 = rank1;
  312.    if(rank0 <= 0) rank0 = rank;
  313.    if(!done_stopprint) outheader();
  314.    t1 = tt_head;
  315.    for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) {
  316.      if(flg) write(rfile, t1, sizeof(struct toptenentry));
  317.      if(done_stopprint) continue;
  318.       if(rank > flags.end_top &&
  319.         (rank < rank0-flags.end_around || rank > rank0+flags.end_around)
  320.         && (!flags.end_own || strncmp(t1->str, t0->str, NAMSZ)))
  321.           continue;
  322.       if(rank == rank0-flags.end_around &&
  323.          rank0 > flags.end_top+flags.end_around+1 &&
  324.          !flags.end_own)
  325.         (void) putchar('\n');
  326.      if(rank != rank0)
  327.       (void) outentry(rank, t1, 0);
  328.      else if(!rank1)
  329.       (void) outentry(rank, t1, 1);
  330.      else {
  331.       int t0lth = outentry(0, t0, -1);
  332.       int t1lth = outentry(rank, t1, t0lth);
  333.       if(t1lth > t0lth) t0lth = t1lth;
  334.       (void) outentry(0, t0, t0lth);
  335.      }
  336.    }
  337.    if(rank0 >= rank)
  338.       (void) outentry(0, t0, 1);
  339.    (void) close(rfile);
  340.  
  341. /* 12nov85 djw */
  342.    getret();
  343. }
  344.  
  345. outheader() {
  346. char linebuf[BUFSZ];
  347. register char *bp;
  348.    (void) strcpy(linebuf, "Number Points  Name");
  349.    bp = eos(linebuf);
  350.    while(bp < linebuf + COLNO - 9) *bp++ = ' ';
  351.    (void) strcpy(bp, "Hp [max]");
  352.    myputs(linebuf);
  353. }
  354.  
  355. /* so>0: standout line; so=0: ordinary line; so<0: no output, return lth */
  356. int
  357. outentry(rank,t1,so) register struct toptenentry *t1; {
  358. boolean quit = FALSE, killed = FALSE, starv = FALSE;
  359. char linebuf[BUFSZ];
  360.    linebuf[0] = 0;
  361.    if(rank) Sprintf(eos(linebuf), "%3d", rank);
  362.       else Sprintf(eos(linebuf), "   ");
  363.    Sprintf(eos(linebuf), " %6ld %8s", t1->points, t1->str);
  364.    if(t1->plchar == 'X') Sprintf(eos(linebuf), " ");
  365.    else Sprintf(eos(linebuf), "-%c ", t1->plchar);
  366.     if(!strncmp("escaped", t1->death, 7)) {
  367.       if(!strcmp(" (with amulet)", t1->death+7))
  368.         Sprintf(eos(linebuf), "escaped the dungeon with amulet");
  369.       else
  370.         Sprintf(eos(linebuf), "escaped the dungeon [max level %d]",
  371.           t1->maxlvl);
  372.     } else {
  373.      if(!strncmp(t1->death,"quit",4))
  374.        Sprintf(eos(linebuf), "quit"), quit = TRUE;
  375.      else if(!strcmp(t1->death,"choked"))
  376.        Sprintf(eos(linebuf), "choked in his food");
  377.      else if(!strncmp(t1->death,"starv",5))
  378.        Sprintf(eos(linebuf), "starved to death"), starv = TRUE;
  379.      else Sprintf(eos(linebuf), "was killed"), killed = TRUE;
  380.      Sprintf(eos(linebuf), " on%s level %d",
  381.        (killed || starv) ? "" : " dungeon", t1->level);
  382.      if(t1->maxlvl != t1->level)
  383.        Sprintf(eos(linebuf), " [max %d]", t1->maxlvl);
  384.      if(quit && t1->death[4]) Sprintf(eos(linebuf), t1->death + 4);
  385.    }
  386.    if(killed) Sprintf(eos(linebuf), " by %s%s",
  387.      !strncmp(t1->death, "the ", 4) ? "" :
  388.      index(vowels,*t1->death) ? "an " : "a ",
  389.      t1->death);
  390.    Sprintf(eos(linebuf), ".");
  391.    if(t1->maxhp) {
  392.      register char *bp = eos(linebuf);
  393.      char hpbuf[10];
  394.      int hppos;
  395.      Sprintf(hpbuf, (t1->hp > 0) ? itoa(t1->hp) : "-");
  396.      hppos = COLNO - 7 - strlen(hpbuf);
  397.      if(bp <= linebuf + hppos) {
  398.        while(bp < linebuf + hppos) *bp++ = ' ';
  399.        (void) strcpy(bp, hpbuf);
  400.        Sprintf(eos(bp), " [%d]", t1->maxhp);
  401.      }
  402.    }
  403.    if(so == 0) myputs(linebuf);
  404.    else if(so > 0) {
  405.      register char *bp = eos(linebuf);
  406.      if(so >= COLNO) so = COLNO-1;
  407.      while(bp < linebuf + so) *bp++ = ' ';
  408.      *bp = 0;
  409.      standoutbeg();
  410.      myputs(linebuf);
  411.      standoutend();
  412.      (void) myputchar('\n');
  413.    }
  414.    return(strlen(linebuf));
  415. }
  416.  
  417. char *
  418. itoa(a) int a; {
  419. static char buf[12];
  420.    Sprintf(buf,"%d",a);
  421.    return(buf);
  422. }
  423.  
  424. char *
  425. ordin(n) int n; {
  426. register int d = n%10;
  427.    return((d==0 || d>3 || n/10==1) ? "th" : (d==1) ? "st" :
  428.       (d==2) ? "nd" : "rd");
  429. }
  430.  
  431. clearlocks(){
  432. register int x;
  433. #ifndef AMIGA
  434.    (void) signal(SIGHUP,SIG_IGN);
  435. #endif
  436.    for(x = 1; x <= maxdlevel; x++) {
  437.       glo(x);
  438.       (void) unlink(lock);   /* not all levels need be present */
  439.    }
  440.    *index(lock,'.') = 0;
  441.    (void) unlink(lock);
  442. }
  443.  
  444. #ifdef NOSAVEONHANGUP
  445. hangup(){
  446. #ifndef AMIGA
  447.    (void) signal(SIGINT,SIG_IGN);
  448. #endif
  449.    clearlocks();
  450.    hackexit(1);
  451. }
  452. #endif NOSAVEONHANGUP
  453.  
  454. char *
  455. eos(s) register char *s; {
  456.    while(*s) s++;
  457.    return(s);
  458. }
  459.  
  460. /* it is the callers responsibility to check that there is room for c */
  461. charcat(s,c) register char *s, c; {
  462.    while(*s) s++;
  463.    *s++ = c;
  464.    *s = 0;
  465. }
  466.  
  467. prscore(argc,argv) int argc; char **argv; {
  468.    extern char *hname;
  469.    char *player0;
  470.    char **players;
  471.    int playerct;
  472.    int rank;
  473.    register struct toptenentry *t1;
  474.    char *recfile = "record";
  475.    int  rfile;
  476.    register int flg = 0;
  477.    register int i;
  478.  
  479.    if((rfile = open(recfile,O_RDONLY)) < 0)
  480.       {
  481.       myputs("Cannot open record file!");
  482.       return;
  483.       }
  484.  
  485.    if(argc > 1 && !strncmp(argv[1], "-s", 2)){
  486.       if(!argv[1][2]){
  487.          argc--;
  488.          argv++;
  489.       } else if(!argv[1][3] && index("CFKSTWX", argv[1][2])) {
  490.          argv[1]++;
  491.          argv[1][0] = '-';
  492.       } else   argv[1] += 2;
  493.    }
  494.    if(argc <= 1){
  495.       player0 = getlogin();
  496.       if(!player0) player0 = "player";
  497.       playerct = 1;
  498.       players = &player0;
  499.    } else {
  500.       playerct = --argc;
  501.       players = ++argv;
  502.    }
  503.    myputchar('\n');
  504.  
  505.    t1 = tt_head = newttentry();
  506.    for(rank = 1; ; rank++) {
  507.      if (read(rfile, t1, sizeof(struct toptenentry)) !=
  508.            sizeof(struct toptenentry))
  509.         t1->points = 0;
  510.      if(t1->points == 0) break;
  511.      for(i = 0; i < playerct; i++){
  512.       if(strcmp(players[i], "all") == 0 ||
  513.          strncmp(t1->str, players[i], NAMSZ) == 0 ||
  514.         (players[i][0] == '-' &&
  515.          players[i][1] == t1->plchar &&
  516.          players[i][2] == 0) ||
  517.         (digit(players[i][0]) && rank <= atoi(players[i])))
  518.          flg++;
  519.      }
  520.      t1 = t1->tt_next = newttentry();
  521.    }
  522.    (void) close(rfile);
  523.    if(!flg) {
  524.       myprintf("Cannot find any entries for ");
  525.       if(playerct > 1) myprintf("any of ");
  526.       for(i=0; i<playerct; i++)
  527.          myprintf("%s%s", players[i], (i<playerct-1)?", ":".\n");
  528.       myprintf("Call is: %s -s [playernames]\n", hname);
  529.       return;
  530.    }
  531.  
  532.    outheader();
  533.    t1 = tt_head;
  534.    for(rank = 1; t1->points != 0; rank++, t1 = t1->tt_next) {
  535.       for(i = 0; i < playerct; i++){
  536.          if(strcmp(players[i], "all") == 0 ||
  537.             strncmp(t1->str, players[i], NAMSZ) == 0 ||
  538.            (players[i][0] == '-' &&
  539.             players[i][1] == t1->plchar &&
  540.             players[i][2] == 0) ||
  541.            (digit(players[i][0]) && rank <= atoi(players[i])))
  542.             goto out;
  543.       }
  544.       continue;
  545.    out:
  546.      (void) outentry(rank, t1, 0);
  547.    }
  548. }
  549.  
  550.